package system;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import bean.PostBean;
import dao.DAO;
import dao.PostDAO;


/**
 * Class for management of Posts
 * @author Anne Lorayne, Laura Dutra, Otavio Lima
 *
 */
public class Post {

	private List<Comment> commentsList;
	private List<Media> pictureList;
	private List<Media> soundList;
	private List<Media> movieList;
	private PostBean post;

	/**
	 * Constructor
	 * @param id - id of post
	 * @param title - title of post
	 * @param content - content of post
	 * @param date - date of post
	 */
	public Post(String id, String title, String content, String date){
		post = new PostBean(id, title, content, date);
		if(!PostDAO.getInstance().contains(post))
			PostDAO.getInstance().save(post);
		
		commentsList = Comment.getCommentsByPost(id);
		
		pictureList = Picture.getPictureByPost(id);
		soundList = Sound.getSoundByPost(id);
		movieList = Movie.getMovieByPost(id);
	}

	
	/**
	 * Updates a Post
	 * @param title
	 * @param content
	 * @return true if post was updated
	 * @throws Exception 
	 */
	
	public void update(String attribute, String value) throws Exception {
		
		if(attribute.equals("titulo")){
			if(value == null || value.trim().equals(""))
				throw new Exception("Título obrigatório");
			post.setTitle(value);
		}else if(attribute.equals("texto"))
			post.setContent(value);
		else
			throw new Exception("Atributo inválido");
		PostDAO.getInstance().update(post);
	}
		

	/**
	 * Deletes the post of system
	 * @return true if post was deleted
	 */
	
	public boolean delete() {
		
		for(Iterator<Comment> it = commentsList.iterator(); it.hasNext();)
			it.next().delete();
		for(Iterator<Media> it = pictureList.iterator(); it.hasNext();)
			it.next().delete();
		for(Iterator<Media> it = soundList.iterator(); it.hasNext();)
			it.next().delete();
		for(Iterator<Media> it = movieList.iterator(); it.hasNext();)
			it.next().delete();
		
		return PostDAO.getInstance().delete(post);

	}
	
	/**
	 * Gets information of attribute of post
	 * @param postID - id of post
	 * @param attribute
	 * @return information of attribute of post
	 * @throws Exception if the attribute is not valid
	 */
	@SuppressWarnings( { "rawtypes", "unchecked" })
	public String getPostInformation(String attribute) throws Exception {
		
		Map<String, String> pt_to_en = new HashMap<String, String>();

		{
			pt_to_en.put("titulo", "Title");
			pt_to_en.put("texto", "Content");
			pt_to_en.put("data_criacao", "Date");
		}

		try {
			Class postBeanClass = post.getClass();
			Method thisMethod = postBeanClass.getMethod("get"
					+ pt_to_en.get(attribute), (Class[]) null);

			Object result = thisMethod.invoke(post,
					(Object[]) null); // we can receive a null
			return result.toString();
		} catch (Exception e) {
			throw new Exception("Atributo inválido");
		}
	}
	
	
	/**
	 * Return true if post contains text
	 * @param text
	 * @return true if post contains text
	 */
	public boolean hasText(String text){
		return post.getTitle().contains(text) || post.getContent().contains(text);
	}

	/**
	 * Return id of post
	 * @return id of post
	 */
	public String getID() {
		return post.getID();
	}



	//Media Operations
	/**
	 * 	Add a Picture to post
	 * @param url
	 * @param description
	 * @return true if picture was added
	 */
	public String addPicture(String url, String description) {
		if(url != null && !url.equals("")){
			String id = lastMediaId()+ "pic";
			pictureList.add(new Picture(id , url, description));
			return id;
		}
		return null;
	}

	/**
	 * Remove the picture passed as parameter
	 * @param pictureId
	 */
	public void removePicture(String pictureId) {
		Media m = getMedia(pictureList.iterator(), pictureId);
		if(m != null){
			pictureList.remove(m);
			m.delete();
		}
		; //throw Exception
	}
	
	/**
	 * 	Add a Sound to post
	 * @param url
	 * @param description
	 * @return sound id
	 */
	public String addSound(String url, String description) {
		if(url != null && !url.equals("")){
			String id = lastMediaId() + "sou";
			soundList.add(new Sound(id, url, description));
			return id;
		}
		return null;
	}

	/**
	 * Remove the sound passed as parameter
	 * @param soundId
	 */
	public void removeSound(String soundId) {
		Media m = getMedia(soundList.iterator(), soundId);
		if(m == null)
			; //throw Exception
		soundList.remove(m);
		m.delete();

	}

	
	/**
	 * 	Add a Movie to post
	 * @param url
	 * @param description
	 * @return true if movie was added
	 */
	public String addMovie(String url, String description) {
		if(url != null && !url.equals("")){
			String id = lastMediaId() + "mov";
			movieList.add(new Movie(id, url, description));
			return id;
		}
		return null;
	}

	/**
	 * Remove the movie passed as parameter
	 * @param movieId
	 */
	public void removeMovie(String movieId) {
		Media m = getMedia(movieList.iterator(), movieId);
		if(m != null){
			movieList.remove(m);
			m.delete();
		}
		

	}
	
	/**
	 * Returns picture at index
	 * @param index
	 * @return picture at index
	 */
	public String getPictureId(long index) throws Exception{
		if(index <0 || index >= pictureList.size())
			throw new Exception("Índice incorreto");
		return pictureList.get((int)index).getID();
	}
	
	/**
	 * Returns sound at index
	 * @param index
	 * @return sound at index
	 */
	public String getSoundId(long index) throws Exception{
		if(index <0 || index >= soundList.size())
			throw new Exception("Índice incorreto");
		return soundList.get((int)index).getID();
	}
	
	/**
	 * Returns movie at index
	 * @param index
	 * @return movie at index
	 */
	public String getMovieId(long index) throws Exception{
		if(index <0 || index >= movieList.size())
			throw new Exception("Índice incorreto");
		return movieList.get((int)index).getID();
	}
	
	/**
	 * Gets number of sounds of post
	 * @return number of sounds of post
	 */
	public long getNumberOfSounds(){
		return soundList.size();
	}

	/**
	 * Gets number of pictures of post
	 * @return number of pictures of post
	 */
	public long getNumberOfPictures(){
		return pictureList.size();
	}
	
	/**
	 * Gets number of movies of post
	 * @return number of movies of post
	 */
	public long getNumberOfMovies(){
		return movieList.size();
	}
	
	/**
	 * Returns true if post has sound
	 * @param id
	 * @return true if post has sound
	 */
	
	public boolean hasSound(String id){
		Iterator<Media> it = soundList.iterator();
		return getMedia(it, id) != null;
	}
	
	/**
	 * Returns true if post has picture
	 * @param pictureId
	 * @return true if post has picture
	 */
	public boolean hasPicture(String pictureId) {
		Iterator<Media> it = pictureList.iterator();
		return getMedia(it, pictureId) != null;
	}
	
	/**
	 * Returns true if post has movie
	 * @param pictureId
	 * @return true if post has movie
	 */
	
	public boolean hasMovie(String id) {
		Iterator<Media> it = movieList.iterator();
		return getMedia(it, id) != null;
	}

	/**
	 * Returns the description of a media
	 * @param mediaId
	 * @return the description of a media
	 */
	public String getMediaDescription(String mediaId) {
		Media media = getMedia(pictureList.iterator(), mediaId);
		if(media != null)
			return media.getDescription();
		media = getMedia(movieList.iterator(), mediaId);
		if(media != null)
			return media.getDescription();
		media = getMedia(soundList.iterator(), mediaId);
		if(media != null)
			return media.getDescription();
		
		return null;
	}

	/**
	 * Returns the data of a media
	 * @param mediaId
	 * @return the data of a media
	 */
	public String getMediaData(String mediaId) {
		Media media = getMedia(pictureList.iterator(), mediaId);
		if(media != null)
			return media.getURL();
		media = getMedia(movieList.iterator(), mediaId);
		if(media != null)
			return media.getURL();
		media = getMedia(soundList.iterator(), mediaId);
		if(media != null)
			return media.getURL();
		
		return null;
	}
	
	//Comment Operations
	/**
	 * Add comment to post
	 * @param comment
	 * @return true if post was added
	 */
	public String addComment(String comment, String login) {
		if(comment != null && !comment.equals("")){
			String id = lastCommentId();
			commentsList.add(new Comment( id, comment, login));
			return id;
		}
		return null;
	}

	/**
	 * Add a comment for a comment of post
	 * @param commentId
	 * @param comment
	 * @return true if comment was added
	 */
	public boolean addCommentToComment(String commentId, String comment){
		Comment dummy = new Comment(commentId, "", "");
		if(commentsList.indexOf(dummy) >= 0)
			return commentsList.get(commentsList.indexOf(dummy)).addCommentToComment(comment);
		return false;
	}


	/**
	 * Retrieves all posts of a blog
	 * @param blogId - id of blog
	 * @return list of posts of a blog
	 */
	public static List<Post> getAllPostOfBlog(String blogId){
		PostBean post;
		DAO<PostBean> postDAO;
		postDAO = PostDAO.getInstance();
		List<PostBean> list = postDAO.list();
		List<Post> postsByBlog = new ArrayList<Post>();
		for(Iterator<PostBean> it = list.iterator(); it.hasNext();){
			post = it.next();
			if(isPostOfBlog(post.getID(), blogId)){
				postsByBlog.add(new Post(post.getID(), post.getTitle(), post.getContent(), post.getDate()));
			}
		}
		return postsByBlog;
	}
	

	//Private methods
	/**
	 * Returns boolean if is blog's post 
	 * @param postId
	 * @param blogId
	 * @return
	 */
	private static boolean isPostOfBlog(String postId, String blogId){
		if(postId.length() > blogId.length())
			if (postId.substring(0, blogId.length()).equals(blogId))
				return true;
		return false;
	}
	
	/**
	 * Returns the last id of media
	 * @return last id of media
	 */
	private String lastMediaId(){
		post.setLastMediaId(String.valueOf(Integer.parseInt(post.getLastMediaId()) + 1));
		
		return getID() + "m" + post.getLastMediaId();
	}
	
	/**
	 * Returns the last id of comment
	 * @return last id of comment
	 */
	private String lastCommentId(){
		post.setLastCommentId(String.valueOf(Integer.parseInt(post.getLastCommentId()) + 1));
		
		return getID() + "c" + post.getLastCommentId();
	}
	
	/**
	 * Retrieves the media with the id passed as parameter
	 * @param it
	 * @param mediaId
	 * @return Media
	 */
	private Media getMedia(Iterator<Media> it, String mediaId){
		Media media;
		while(it.hasNext()){
			media = it.next();
			if(media.getID().contains(mediaId))
				return media;
		}
		return null;
	}


	/**
	 * Retrieves the number of comments of post
	 * @return number of comments
	 */
	public long getNumberOfComments() {
		return commentsList.size();
	}


	/**
	 * Retrieves the id of comment of the index passed as parameter
	 * @param index
	 * @return commentId
	 */
	public String getComment(int index) {
		return commentsList.get(index).getID();
	}


	/**
	 * Checks if the post comment contains passed as parameter
	 * @param id
	 * @return true 
	 * 			- if post contains comment
	 * 		   false
	 * 			- otherwise
	 */
	public boolean hasComment(String commentId) {
		Iterator<Comment> it = commentsList.iterator();
		Comment comment;
		while(it.hasNext()){
			comment = it.next();
			if(comment.getID().contains(commentId))
				return true;
		}
		return false;
	}

	/**
	 * Retrieves the comment's text passed as parameter
	 * @param commentId
	 * 			- identifier of the comment that the text will be recovered
	 * @return comment's text
	 * @throws Exception
	 */
	public String getCommentText(String commentId) {
		Iterator<Comment> it = commentsList.iterator();
		Comment comment;
		while(it.hasNext()){
			comment = it.next();
			if(comment.getID().contains(commentId))
				return comment.getComment();
		}
		return null;
		
	}

	/**
	 * Retrieves the comment's author passed as parameter
	 * @param commentId
	 * 			- identifier of the comment that the author will be recovered
	 * @return comment's author
	 * @throws Exception
	 */
	public String getCommentAuthor(String commentId) {
		Iterator<Comment> it = commentsList.iterator();
		Comment comment;
		while(it.hasNext()){
			comment = it.next();
			if(comment.getID().equals(commentId)){
				return comment.getAuthor();
			}
		}
		return null;

		
	}


	/**
	 * Returns a number of comments by login passed as parameter
	 * @param login
	 * @return number of comments
	 */
	public int getNumberOfCommentsByLogin(String login) {
		int numberOfComments = 0;
		for(Iterator<Comment> it = commentsList.iterator(); it.hasNext();){
			if(it.next().getAuthor().equals(login))
				numberOfComments ++;
		}
		
		return numberOfComments;
	}
	
}
